package org.budo.mybatis.dao.statement.builder.creator;

import java.lang.reflect.Field;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;

import org.apache.ibatis.session.Configuration;
import org.budo.mybatis.dao.statement.builder.impl.DefaultStatementBuilder;
import org.budo.support.lang.util.ReflectUtil;
import org.budo.support.lang.util.StringUtil;

/**
 * @author lmw
 */
public class FindByExampleStatementCreator extends AbstractStatementCreator {
    public FindByExampleStatementCreator(Configuration configuration, DefaultStatementBuilder statementBuilder) {
        super(configuration, statementBuilder);
    }

    protected String getStatementId() {
        return STATEMENT_FIND_BY_EXAMPLE;
    }

    protected String createStatement(Class<?> entityType) {
        String tableName = this.getStatementBuilder().getEntityConfiger().getTableName(entityType);
        String resultMapOrResultType = this.getStatementBuilder().resultMapOrResultType(this.getConfiguration(), entityType, null);

        String whereSql = "<where>\n";

        List<Field> fields = ReflectUtil.getAllFields(entityType);
        for (Field field : fields) {
            Column column = field.getAnnotation(Column.class);
            if (null != column && column.updatable()) {
                String columnName = this.getStatementBuilder().getEntityConfiger().getColumnName(field);
                whereSql += _12 + "<if test=\"" + field.getName() + " != null\"> AND " + columnName + " = #{" + field.getName() + "} </if>\n";
                continue;
            }

            if (null != field.getAnnotation(OneToOne.class)//
                    || null != field.getAnnotation(ManyToOne.class)) {
                String idFieldName = this.getStatementBuilder().getEntityConfiger().getIdFieldName(field.getType());
                String joinColumnName = this.getStatementBuilder().getEntityConfiger().getJoinColumnName(field);

                if (StringUtil.isEmpty(joinColumnName)) {
                    continue;
                }

                whereSql += _12 + "<if test=\"" + field.getName() + " != null and " + field.getName() + "." + idFieldName + " != null\"> " //
                        + " AND " + joinColumnName + " = #{" + field.getName() + "." + idFieldName + "} " //
                        + " </if>\n";
                continue;
            }
        }

        whereSql += _8 + "</where>";

        String statementXml = _4 + "<select id=\"$findByExample\" " + resultMapOrResultType + " parameterType=\"" + entityType.getName() + "\">\n" //
                + _8 + "SELECT * FROM " + tableName + "\n"//
                + _8 + whereSql + "\n" //
                + _8 + " LIMIT 1\n" //
                + _4 + "</select>"; //

        return statementXml;
    }
}